import { jsmain } from "./testjs";
// 如何验证一个素数
export function isPrime(n: number) {
  let divisor = 2;
  while (n > divisor) {
    if (n % divisor == 0) {
      console.log(n, " is not 一个素数 ");
      return false;
    } else divisor++;
  }
  console.log(n, " is一个素数 ");
  return true;
}

// Q：如何求出一个数的所有素数因子？
// A：执行一个while循环。开始除以2，如果不能整除，记录这个除数，直到完成。
function primeFactors(n: number) {
  const factors = [];
  let divisor = 2;
  while (n > 2) {
    if (n % divisor == 0) {
      factors.push(divisor);
      n = n / divisor;
    } else {
      divisor++;
    }
  }
  return factors;
}

// Q：如何获得第n个斐波纳契数字？
// A：我创建一个数组并从迭代开始。
function fibonacci(n: number) {
  const fibo = [0, 1];
  if (n <= 2) return 1;
  for (let i = 2; i <= n; i++) {
    fibo[i] = fibo[i - 1] + fibo[i - 2];
  }
  return fibo[n];
}

// 最大公约数
function greatestCommonDivisor(a: number, b: number) {
  let divisor = 2,
    greatestDivisor = 1;
  //if u pass a -ve number this will not work. fix it dude!!
  if (a < 2 || b < 2) return 1;
  while (a >= divisor && b >= divisor) {
    if (a % divisor == 0 && b % divisor == 0) {
      greatestDivisor = divisor;
    }
    divisor++;
  }
  return greatestDivisor;
}
// 最大公约数
function greatestCommonDivisor_b(a: number, b: number) {
  if (b == 0) return a;
  else return greatestCommonDivisor(b, a % b);
}

//去重
function removeDuplicate(arr: number[]) {
  const exists = [];
  const outArr = [];
  let elm;
  for (let i = 0; i < arr.length; i++) {
    elm = arr[i];
    if (exists[elm]) {
      outArr.push(elm);
      exists[elm] = true;
    }
  }
  return outArr;
}
// 字符串反向
// Q：如何在JavaScript中反转字符串？
// A：可以遍历字符串并将字母连接到新字符串。
function reverse(str: string) {
  let rtnStr = "";
  for (let i = str.length - 1; i >= 0; i--) {
    rtnStr += str[i];
  }
  return rtnStr;
}
function reverse2(str: string) {
  const rtnStr = [];
  if (!str || typeof str != "string" || str.length < 2) return str;
  for (let i = str.length - 1; i >= 0; i--) {
    rtnStr.push(str[i]);
  }
  return rtnStr.join("");
}
function reverse3(str1: string) {
  const str = str1.split("");
  const len = str.length,
    halfIndex = Math.floor(len / 2) - 1;
  let revStr;

  for (let i = 0; i <= halfIndex; i++) {
    revStr = str[len - i - 1];
    str[len - i - 1] = str[i];
    str[i] = revStr;
  }
  return str.join("");
}
function reverse4(str: string) {
  if (str === "") {
    return "";
  } else {
    return reverse(str.substr(1)) + str.charAt(0);
  }
}
function reverse5(str: string) {
  if (!str || str.length < 2) return str;
  return str.split("").reverse().join("");
}
function reverseWords(str: string) {
  return str.split(" ").reverse();
}

//原位反转
function reverseInPlace(str: string) {
  return str.split(" ").reverse().join(" ").split("").reverse().join("");
}
reverseInPlace("I am the good boy"); // = "I ma eht doog yob"

//第一个非重复字符
function firstNonRepeatChar(str: string) {
  const len = str.length;
  let char;
  const charCount = {};
  for (let i = 0; i < len; i++) {
    char = str[i];
    if (charCount[char]) {
      charCount[char]++;
    } else charCount[char] = 1;
  }
  for (const j in charCount) {
    if (charCount[j] == 1) return j;
  }
}

//删除重复的字符
function removeDuplicateChar(str: string) {
  const len = str.length;
  let char;
  const charCount = {};
  const newStr = [];
  for (let i = 0; i < len; i++) {
    char = str[i];
    if (charCount[char]) {
      charCount[char]++;
    } else charCount[char] = 1;
  }
  for (const j in charCount) {
    if (charCount[j] == 1) newStr.push(j);
  }
  return newStr.join("");
}

// 回文检查
function isPalindrome(str: string) {
  const len = str.length;

  for (let i = 0; i < len / 2; i++) {
    if (str[i] !== str[len - 1 - i]) return false;
  }
  return true;
}
// 回文检查
function checkPalindrom(str: string) {
  return str == str.split("").reverse().join("");
}
// 找缺失的数字
function missingNumber(arr: any) {
  const n = arr.length + 1;
  let sum = 0;
  const expectedSum = (n * (n + 1)) / 2;
  for (let i = 0, len = arr.length; i < len; i++) {
    sum += arr[i];
  }
  return expectedSum - sum;
}
// 两数之和: 在一个未排序的数组中找出是否有任意两数之和等于给定的数？
function sumFinder(arr: number[], sum: number) {
  const len = arr.length;
  for (let i = 0; i < len - 1; i++) {
    for (let j = i + 1; j < len; j++) {
      if (arr[i] + arr[j] == sum) return true;
    }
  }
  return false;
}

// 最大和
function topSum(arr: number[]) {
  let biggest = arr[0],
    second = arr[1],
    i = 2;
  const len = arr.length;
  if (len < 2) return null;
  if (biggest < second) {
    biggest = arr[1];
    second = arr[0];
  }
  for (; i < len; i++) {
    if (arr[i] > biggest) {
      second = biggest;
      biggest = arr[i];
    } else if (arr[i] > second) {
      second = arr[i];
    }
  }
  return biggest + second;
}
//统计零
function countZero(n) {
  let count = 0;
  while (n > 0) {
    count += Math.floor(n / 10);
    n = n / 10;
  }
  return count;
}

//在字符串中匹配子字符串
function subStringFinder(str: string, subStr: string) {
  const len = str.length,
    subLen = subStr.length;
  let idx = 0;
  let j = 0;
  for (let i = 0; i < len; i++) {
    if (str[i] == subStr[j]) j++;
    else j = 0; //check starting point or a match
    if (j == 0) idx = i;
    else if (j == subLen) return idx;
  }
  return -1;
}

// = 0subStringFinder('abbcdabbbbbck', 'bck')// = 9//doesn't work for this one.subStringFinder('abbcdabbbbbck', 'bbbck') // = -1
// 如何获取字符串中的所有排列？
function permutations(str:string) {
  const arr = str.split(""),
    len = arr.length,
    perms = [];
  let rest, picked, restPerms, next;
  if (len == 0) return [str];
  for (let i = 0; i < len; i++) {
    rest = Object.create(arr);
    picked = rest.splice(i, 1);
    restPerms = permutations(rest.join(""));
    for (let j = 0, jLen = restPerms.length; j < jLen; j++) {
      next = picked.concat(restPerms[j]);
      perms.push(next.join(""));
    }
  }
  return perms;
}

export function main() {
  greatestCommonDivisor(14, 21);
  greatestCommonDivisor_b(69, 169); // = 1

  primeFactors(69); // = [3, 23]
  fibonacci(12);
  isPrime(144);
  // = 137
  removeDuplicate([1, 3, 3, 3, 1, 5, 6, 7, 8, 1]); // = [1, 3, 5, 6, 7, 8]
  console.log("reverse1:", reverse("you are a nice dude"));
  console.log("reverse2:", reverse2("you are a nice dude"));
  console.log("reverse3:", reverse3("you are a nice dude"));
  console.log("reverse4:", reverse4("you are a nice dude"));
  console.log("reverse5:", reverse5("you are a nice dude"));
  console.log("reverseWords:", reverseWords("you are a nice dude"));
  console.log("reverseInPlace:", reverseInPlace("you are a nice dude"));
  console.log(
    "第一个非重复字符:",
    firstNonRepeatChar("the quick brown fox jumps then quickly blow air")
  ); // = "f"
  console.log(
    "removeDuplicateChar:",
    removeDuplicateChar("Learn more javascript dude")
  );
  // = "Lnmojvsciptu"

  isPalindrome("madam"); // = trueisPalindrome('toyota')// = false
  checkPalindrom("toyota");

  missingNumber([5, 2, 6, 1, 3]); // = 4
  sumFinder([6, 4, 3, 2, 1, 7], 9);
  topSum([1, 2, 3, 4, 5, 6]);
  countZero(2014); // = 223
  subStringFinder("abbcdabbbbbck", "ab");
  // permutations("abbcdabbbbbck")
  jsmain();
}
